#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <stdint.h>
#include <fcntl.h>
#include <time.h>
#include "media_lib.h"
#include "../proto/netradio_proto.h" // 引入协议头

// -------------------------- 全局变量 --------------------------
static int multicast_fd = -1;          // 多播UDP socket
static char *chn_list_buf = NULL;      // 频道列表数据缓冲区
static int chn_list_len = 0;           // 频道列表数据长度
static volatile int server_running = 1; // 服务器运行标志（控制退出，添加volatile确保可见性）
static pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER; // 退出同步锁

// -------------------------- 线程池结构定义 --------------------------
// 任务类型：发送频道列表 / 发送频道音频
typedef enum {
    TASK_LIST_SEND,  // 定时发送频道列表
    TASK_CHN_SEND    // 持续发送单个频道音频
} TaskType;

// 线程池任务结构体
typedef struct {
    TaskType type;       // 任务类型
    chnid_t chnid;       // 仅TASK_CHN_SEND有效：频道ID
} ThreadPoolTask;

// 线程池结构体（管理线程和任务）
typedef struct {
    ThreadPoolTask *queue;   // 任务队列
    int queue_size;          // 队列最大容量
    int task_count;          // 当前任务数
    int front;               // 队头（取任务）
    int rear;                // 队尾（加任务）
    
    pthread_t *threads;      // 工作线程数组
    int thread_num;          // 工作线程数量
    
    pthread_mutex_t mutex;   // 保护任务队列的互斥锁
    pthread_cond_t cond;     // 任务通知条件变量
    int running;             // 线程池运行标志
} ThreadPool;

// -------------------------- 线程池核心函数 --------------------------
// 声明线程池工作函数（pthread_create 要求返回 void*）
void *thread_pool_worker(void *arg);
/*
 * 初始化线程池
 * @param thread_num 工作线程数量
 * @param queue_size 任务队列最大容量
 * @return 线程池指针（失败返回NULL）
 */
ThreadPool *thread_pool_init(int thread_num, int queue_size) {
    ThreadPool *pool = (ThreadPool *)malloc(sizeof(ThreadPool));
    if (pool == NULL) {
        perror("malloc thread pool");
        return NULL;
    }

    // 初始化任务队列
    pool->queue_size = queue_size;
    pool->queue = (ThreadPoolTask *)malloc(sizeof(ThreadPoolTask) * queue_size);
    if (pool->queue == NULL) {
        perror("malloc task queue");
        free(pool);
        return NULL;
    }
    pool->front = 0;
    pool->rear = 0;
    pool->task_count = 0;

    // 初始化工作线程
    pool->thread_num = thread_num;
    pool->threads = (pthread_t *)malloc(sizeof(pthread_t) * thread_num);
    if (pool->threads == NULL) {
        perror("malloc threads");
        free(pool->queue);
        free(pool);
        return NULL;
    }

    // 初始化同步锁和条件变量
    if (pthread_mutex_init(&pool->mutex, NULL) != 0 ||
        pthread_cond_init(&pool->cond, NULL) != 0) {
        perror("init mutex/cond");
        free(pool->threads);
        free(pool->queue);
        free(pool);
        return NULL;
    }

    pool->running = 1;

    // 创建工作线程
    for (int i = 0; i < thread_num; i++) {
        if (pthread_create(&pool->threads[i], NULL, 
            (void *(*)(void *))thread_pool_worker, pool) != 0) {
            perror("pthread_create");
            // 回滚：销毁已创建线程
            pool->running = 0;
            pthread_cond_broadcast(&pool->cond);
            for (int j = 0; j < i; j++) pthread_join(pool->threads[j], NULL);
            pthread_mutex_destroy(&pool->mutex);
            pthread_cond_destroy(&pool->cond);
            free(pool->threads);
            free(pool->queue);
            free(pool);
            return NULL;
        }
    }

    return pool;
}


// 声明频道列表发送函数
void send_chn_list_loop(void);
// 声明频道音频发送函数
void send_chn_data_loop(chnid_t chnid);

/**
 * 线程池工作线程（循环处理任务）
 * @param arg 线程池指针
 */
// 线程池工作函数
void *thread_pool_worker(void *arg) {
    ThreadPool *pool = (ThreadPool *)arg;
    ThreadPoolTask task;

    while (1) {
        // 1. 加锁访问任务队列
        pthread_mutex_lock(&pool->mutex);

        // 2. 队列空且线程池运行中：等待任务通知
        while (pool->task_count == 0 && pool->running) {
            pthread_cond_wait(&pool->cond, &pool->mutex);
        }

        // 3. 线程池已停止：解锁并退出
        if (!pool->running) {
            pthread_mutex_unlock(&pool->mutex);
            break;
        }

        // 4. 提取任务（循环队列）
        task = pool->queue[pool->front];
        pool->front = (pool->front + 1) % pool->queue_size;
        pool->task_count--;

        // 5. 解锁
        pthread_mutex_unlock(&pool->mutex);

        // 6. 处理任务
        switch (task.type) {
            case TASK_LIST_SEND:
                send_chn_list_loop();
                break;
            case TASK_CHN_SEND:
                send_chn_data_loop(task.chnid);
                break;
            default:
                fprintf(stderr, "Unknown task type: %d\n", task.type);
                break;
        }
    }

    return NULL;
}

/**
 * 向线程池添加任务
 * @param pool 线程池指针
 * @param task 待添加任务
 * @return 0成功，-1失败
 */
int thread_pool_add_task(ThreadPool *pool, ThreadPoolTask *task) {
    if (pool == NULL || task == NULL) {
        errno = EINVAL;
        return -1;
    }

    pthread_mutex_lock(&pool->mutex);

    // 队列满：返回重试
    if (pool->task_count >= pool->queue_size) {
        pthread_mutex_unlock(&pool->mutex);
        errno = EAGAIN;
        return -1;
    }

    // 添加任务到队列
    pool->queue[pool->rear] = *task;
    pool->rear = (pool->rear + 1) % pool->queue_size;
    pool->task_count++;

    // 唤醒一个等待的工作线程
    pthread_cond_signal(&pool->cond);

    pthread_mutex_unlock(&pool->mutex);

    return 0;
}

/**
 * 销毁线程池
 * @param pool 线程池指针
 */
void thread_pool_destroy(ThreadPool *pool) {
    if (pool == NULL) return;

    // 停止线程池
    pthread_mutex_lock(&pool->mutex);
    pool->running = 0;
    pthread_mutex_unlock(&pool->mutex);

    // 唤醒所有工作线程
    pthread_cond_broadcast(&pool->cond);

    // 等待所有线程退出
    for (int i = 0; i < pool->thread_num; i++) {
        pthread_join(pool->threads[i], NULL);
    }

    // 释放资源
    pthread_mutex_destroy(&pool->mutex);
    pthread_cond_destroy(&pool->cond);
    free(pool->threads);
    free(pool->queue);
    free(pool);
}

// -------------------------- 多播Socket初始化 --------------------------
/**
 * 初始化多播UDP Socket（设置多播TTL、发送接口）
 * @return Socket fd（失败返回-1）
 */
int multicast_socket_init(void) {
    struct sockaddr_in addr;
    int opt_val = 1;
    struct in_addr local_addr;  // 用于指定发送接口

    // 1. 创建socket（必须先成功创建，才能进行后续操作）
    multicast_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (multicast_fd < 0) {
        perror("socket create failed");
        return -1;  // 创建失败，直接返回
    }

    // 新增：设置socket为非阻塞（避免sendto阻塞）
    int flags = fcntl(multicast_fd, F_GETFL, 0);
    if (flags < 0) {
        perror("fcntl F_GETFL failed");
        close(multicast_fd);
        return -1;
    }
    if (fcntl(multicast_fd, F_SETFL, flags | O_NONBLOCK) < 0) {
        perror("fcntl F_SETFL O_NONBLOCK failed");
        close(multicast_fd);
        return -1;
    }

    // 2. 允许端口重用
    if (setsockopt(multicast_fd, SOL_SOCKET, SO_REUSEADDR, 
        &opt_val, sizeof(opt_val)) < 0) {
        perror("setsockopt SO_REUSEADDR failed");
        close(multicast_fd);  // 失败时关闭socket，避免资源泄漏
        multicast_fd = -1;    // 标记为无效
        return -1;
    }

    // 3. 绑定端口（服务器发送端口，通常与接收端一致）
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(RCV_PORT);  // RCV_PORT=6666
    addr.sin_addr.s_addr = htonl(INADDR_ANY);  // 绑定到任意本地地址
    if (bind(multicast_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        perror("bind failed");
        close(multicast_fd);
        multicast_fd = -1;
        return -1;
    }

    // 4. 指定多播发送接口（ens33的IP，替换为你的实际IP）
    const char *ens33_ip = "192.168.101.134";  // 替换为你的实际IP
    local_addr.s_addr = inet_addr(ens33_ip);
    if (local_addr.s_addr == INADDR_NONE) {  // 检查IP是否有效
        fprintf(stderr, "Invalid IP address: %s\n", ens33_ip);
        close(multicast_fd);
        multicast_fd = -1;
        return -1;
    }

    if (setsockopt(multicast_fd, IPPROTO_IP, IP_MULTICAST_IF, 
        &local_addr, sizeof(local_addr)) < 0) {
        perror("setsockopt IP_MULTICAST_IF failed");
        close(multicast_fd);
        multicast_fd = -1;
        return -1;
    }

    // 初始化成功，打印信息
    printf("Multicast socket ready (fd: %d, sending on %s:%d)\n", 
           multicast_fd, ens33_ip, RCV_PORT);
    return 0;
}

// -------------------------- 频道列表构建与发送 --------------------------
/**
 * 构建频道列表数据（遵循协议struct chn_list_st格式）
 * @param buf 输出：列表数据缓冲区（需手动free）
 * @param len 输出：列表数据总长度
 * @return 0成功，-1失败
 */
int build_chn_list(char **buf, int *len, struct mlib_list_entry *mlib, int chn_count) {
    int total_len = sizeof(chnid_t); // 总长度 = 首字节(CHN_LIST_ID) + 所有list_entry长度
    char *ptr = NULL;

    // 检查输入有效性（避免空指针）
    if (mlib == NULL || chn_count == 0) {
        fprintf(stderr, "[Server] 无效的频道列表（空或无频道）\n");
        return -1;
    }

    // 1. 计算总长度（首字节 + 所有list_entry的len）
    for (int i = 0; i < chn_count; i++) {
        if (mlib[i].descr == NULL) {
            fprintf(stderr, "[Server] 频道%d描述为空\n", mlib[i].chnid);
            return -1;
        }
        // 单个list_entry的len：1(chnid) + 1(len) + 描述长度 + 1('\0')
        len_t entry_len = sizeof(chnid_t) + sizeof(len_t) + strlen(mlib[i].descr) + 1;
        total_len += entry_len;
    }

    // 2. 分配缓冲区
    *buf = (char *)malloc(total_len);
    if (*buf == NULL) {
        perror("[Server] 分配频道列表缓冲区失败");
        return -1;
    }
    ptr = *buf;
    *len = total_len;

    // 3. 填充首字节（CHN_LIST_ID=0）
    *(chnid_t *)ptr = CHN_LIST_ID;
    ptr += sizeof(chnid_t);

    // 4. 填充每个list_entry（复用mlib中的数据）
    for (int i = 0; i < chn_count; i++) {
        struct list_entry *entry = (struct list_entry *)ptr;
        len_t entry_len = sizeof(chnid_t) + sizeof(len_t) + strlen(mlib[i].descr) + 1;

        entry->chnid = mlib[i].chnid;
        entry->len = entry_len;
        strcpy(entry->descr, mlib[i].descr);

        ptr += entry_len;
    }

    printf("[Server] 频道列表构建完成：总长度%d字节，包含%d个频道\n", *len, chn_count);
    return 0;
}

/**
 * 循环发送频道列表（间隔5秒，让新客户端能获取列表）
 */
void send_chn_list_loop(void) {
    struct sockaddr_in mcast_addr;
    socklen_t addr_len = sizeof(mcast_addr);
    memset(&mcast_addr, 0, sizeof(mcast_addr));
    mcast_addr.sin_family = AF_INET;
    mcast_addr.sin_port = htons(RCV_PORT);
    if (inet_pton(AF_INET, GROUP_ADDR, &mcast_addr.sin_addr) <= 0) {
        perror("inet_pton mcast addr");
        return;
    }

    int running;
    // 读取初始运行状态
    pthread_mutex_lock(&exit_mutex);
    running = server_running;
    pthread_mutex_unlock(&exit_mutex);

    while (running) {
        int send_len = sendto(multicast_fd, chn_list_buf, chn_list_len, 0,
                             (struct sockaddr *)&mcast_addr, addr_len);
        if (send_len < 0) {
            if (errno == EAGAIN) { // 非阻塞导致暂时无法发送，重试
                usleep(100000); // 等待100ms再试
                continue;
            }
            fprintf(stderr, "[Server] 发送列表失败：%s\n", strerror(errno));
            sleep(1);
            continue;
        }

        // 使用可被信号打断的延迟（5秒）
        struct timespec req = {5, 0};
        struct timespec rem;
        
        while (1) {
            pthread_mutex_lock(&exit_mutex);
            running = server_running;
            pthread_mutex_unlock(&exit_mutex);
            
            if (!running) break;

            int ret = nanosleep(&req, &rem);
            if (ret == 0) break; // 延迟完成
            if (errno != EINTR) { // 非信号打断的错误
                perror("nanosleep error");
                break;
            }
            req = rem; // 被信号打断，继续等待剩余时间
        }

        // 再次检查运行状态
        pthread_mutex_lock(&exit_mutex);
        running = server_running;
        pthread_mutex_unlock(&exit_mutex);
    }
}

// -------------------------- 频道音频发送 --------------------------
/**
 * 循环发送单个频道的音频数据（遵循协议struct chn_data_st格式）
 * @param chnid 频道ID
 */
void send_chn_data_loop(chnid_t chnid) {
    struct sockaddr_in mcast_addr;
    socklen_t addr_len = sizeof(mcast_addr);
    struct chn_data_st data_pkt;
    int read_len;

    memset(&mcast_addr, 0, sizeof(mcast_addr));
    mcast_addr.sin_family = AF_INET;
    mcast_addr.sin_port = htons(RCV_PORT);
    if (inet_pton(AF_INET, GROUP_ADDR, &mcast_addr.sin_addr) <= 0) {
        perror("inet_pton mcast addr");
        return;
    }
    data_pkt.chnid = chnid;

    int running;
    // 读取初始运行状态
    pthread_mutex_lock(&exit_mutex);
    running = server_running;
    pthread_mutex_unlock(&exit_mutex);

    while (running) {
        // 读取音频数据
        read_len = mlib_read_chn_data(chnid, data_pkt.msg, MSG_SIZE);
        if (read_len < 0) {
            perror("Read channel data");
            sleep(1);
            continue;
        } else if (read_len == 0) {
            fprintf(stderr, "No data for channel %d\n", chnid);
            sleep(1);
            continue;
        }

        // 发送音频数据（处理非阻塞）
        int send_len = sendto(multicast_fd, &data_pkt, sizeof(chnid_t) + read_len, 0,
                             (struct sockaddr *)&mcast_addr, addr_len);
        if (send_len < 0) {
            if (errno == EAGAIN) { // 暂时无法发送，重试
                usleep(10000); // 等待10ms再试（音频需低延迟）
                continue;
            }
            perror("sendto channel data");
            sleep(1);
            continue;
        }

        // 动态计算发送间隔（使用可打断的nanosleep）
        int bitrate = 320000; // 320kbps MP3码率
        if (read_len > 0) {
            int interval = (read_len * 8 * 1000000) / bitrate;
            if (interval < 1000) interval = 1000; // 最小1ms

            struct timespec req, rem;
            req.tv_sec = interval / 1000000;
            req.tv_nsec = (interval % 1000000) * 1000;

            while (1) {
                pthread_mutex_lock(&exit_mutex);
                running = server_running;
                pthread_mutex_unlock(&exit_mutex);
                
                if (!running) break;

                int ret = nanosleep(&req, &rem);
                if (ret == 0) break; // 延迟完成
                if (errno != EINTR) { // 非信号错误
                    perror("nanosleep error");
                    break;
                }
                req = rem; // 被信号打断，继续等待剩余时间
            }
        }

        // 再次检查运行状态
        pthread_mutex_lock(&exit_mutex);
        running = server_running;
        pthread_mutex_unlock(&exit_mutex);
    }
}

// -------------------------- 信号处理（优雅退出） --------------------------
/**
 * 信号处理函数（Ctrl+C触发，设置退出标志）
 * @param sig 信号值（SIGINT/SIGTERM）
 */
void sig_handler(int sig) {
    pthread_mutex_lock(&exit_mutex);
    if (server_running) {
        printf("\nServer is exiting...\n");
        server_running = 0;
    }
    pthread_mutex_unlock(&exit_mutex);
}

// -------------------------- 主函数（流程控制） --------------------------
int main(void) {
    ThreadPool *pool = NULL;
    ThreadPoolTask task;
    struct mlib_list_entry *mlib = NULL;
    int chn_count = 0;

    // 1. 注册信号处理
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = sig_handler;
    sigemptyset(&sa.sa_mask);
    if (sigaction(SIGINT, &sa, NULL) < 0 || sigaction(SIGTERM, &sa, NULL) < 0) {
        perror("sigaction");
        return -1;
    }

    // 2. 初始化多播Socket
    if (multicast_socket_init() != 0) {
        fprintf(stderr, "Multicast socket init failed\n");
        return -1;
    }

    // 3. 获取频道列表
    if (mlib_get_chn_list(&mlib, &chn_count) < 0 || chn_count == 0) {
        fprintf(stderr, "Get channel list failed\n");
        close(multicast_fd);
        return -1;
    }
    printf("[Server] 成功获取 %d 个唯一频道\n", chn_count);

    // 4. 构建频道列表
    if (build_chn_list(&chn_list_buf, &chn_list_len, mlib, chn_count) < 0) {
        fprintf(stderr, "Build channel list failed\n");
        free(mlib);
        close(multicast_fd);
        return -1;
    }
    printf("Channel list built (len: %d bytes)\n", chn_list_len);

    // 5. 优化列表发送时机
    struct sockaddr_in mcast_addr;
    memset(&mcast_addr, 0, sizeof(mcast_addr));
    mcast_addr.sin_family = AF_INET;
    mcast_addr.sin_port = htons(RCV_PORT);
    inet_pton(AF_INET, GROUP_ADDR, &mcast_addr.sin_addr);

    // 5.1 延迟3秒，等待用户启动客户端
    printf("[Server] 等待客户端启动（3秒后发送频道列表）...\n");
    sleep(3);

    // 5.2 连续发送10次列表包
    printf("[Server] 开始连续发送10次频道列表...\n");
    for (int i = 0; i < 10; i++) {
        int send_len = sendto(multicast_fd, chn_list_buf, chn_list_len, 0,
                            (struct sockaddr *)&mcast_addr, sizeof(mcast_addr));
        if (send_len == chn_list_len) {
            printf("[Server] 第%d次发送列表成功（%d字节，ID=0）\n", i+1, send_len);
        } else if (send_len < 0) {
           fprintf(stderr, "[Server] 第%d次发送列表失败：%s\n", i+1, strerror(errno));
        } else {
            fprintf(stderr, "[Server] 第%d次发送列表不完整（发%d字节，需%d字节）\n", i+1, send_len, chn_list_len);
        }
        sleep(1);
    }

    printf("[Server] 列表发送完成，延迟10秒启动音频任务...\n");
    sleep(10);

    // 6. 初始化线程池
    int task_total = 1 + chn_count;
    pool = thread_pool_init(task_total, task_total);
    if (pool == NULL) {
        fprintf(stderr, "Thread pool init failed\n");
        free(mlib);
        free(chn_list_buf);
        close(multicast_fd);
        return -1;
    }
    printf("Thread pool ready (threads: %d, queue size: %d)\n", 
           pool->thread_num, pool->queue_size);

    // 7. 添加频道列表任务
    task.type = TASK_LIST_SEND;
    if (thread_pool_add_task(pool, &task) < 0) {
        perror("Add list task");
        thread_pool_destroy(pool);
        free(mlib);
        free(chn_list_buf);
        close(multicast_fd);
        return -1;
    }
    printf("Added channel list send task\n");

    // 8. 添加音频任务
    for (int i = 0; i < chn_count; i++) {
        task.type = TASK_CHN_SEND;
        task.chnid = mlib[i].chnid;
        if (thread_pool_add_task(pool, &task) < 0) {
            perror("Add channel task");
            thread_pool_destroy(pool);
            free(mlib);
            free(chn_list_buf);
            close(multicast_fd);
            return -1;
        }
        printf("Added channel %d send task (desc: %s)\n", 
               mlib[i].chnid, mlib[i].descr);
    }
    free(mlib);

    // 9. 等待服务器停止
    while (1) {
        pthread_mutex_lock(&exit_mutex);
        int running = server_running;
        pthread_mutex_unlock(&exit_mutex);
        if (!running) break;
        sleep(1);
    }

    // 10. 资源清理（修正释放顺序）
    printf("Releasing resources...\n");
    
    // 先销毁线程池，确保所有工作线程退出
    thread_pool_destroy(pool);
    
    // 关闭多播socket
    if (multicast_fd != -1) {
        close(multicast_fd);
        multicast_fd = -1;
    }
    
    // 释放频道列表缓冲区
    if (chn_list_buf != NULL) {
        free(chn_list_buf);
        chn_list_buf = NULL;
    }
    
    // 销毁媒体库
    mlib_destroy();
    
    // 销毁退出同步锁
    pthread_mutex_destroy(&exit_mutex);
    
    return 0;
}